﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.IO;
using System.Xml.Serialization;

namespace SCG.Prism.Server
{
    //Stores PrismServer user information in XML files
    public class XmlStorage : PrismServerStorage
    {
        //Initialization - set base directory
        protected override void Initialize()
        {
            _baseDirectory = Server.BasePath + @"\Users";
            if (!Directory.Exists(_baseDirectory))
                Directory.CreateDirectory(_baseDirectory);
        }

        //A user exists if there's an XML file with their name in the base directory
        public override bool UserExists(string userName)
        {
            try
            {
                return File.Exists(GetFileNameForUser(userName));
            }
            catch
            {
                return false;
            }
        }

        //User name is OK if it's a valid file name - try to create the file!
        public override bool CheckUserName(string userName, ref string msg)
        {            
            string fileName = GetFileNameForUser(userName);
            try
            {
                if (File.Exists(fileName))
                {
                    msg = "A file for this User already exists";
                    return false;
                }
            }
            catch
            {           
            }

            try
            {
                FileStream fs = File.Create(fileName);
                fs.Close();
                File.Delete(fileName);              
            }
            catch(Exception ex)
            {
                msg = ex.Message;
                return false;
            }
            return true;
        }

        //Validate password - must be at least 4 characters
        public override bool CheckPassword(string password, ref string msg)
        {
            if (password.Contains(" "))
            {
                msg = "Password cannot contain spaces";
                return false;
            }
            if (password.Length < 4)
            {
                msg = "Password must be at least 4 characters long";
                return false;
            }
            return true;
        }

        //Load information from the user's XML file
        public override void PopulateUserInfo(PrismUser user)
        {
            FileStream fs = null;
            try
            {
                string fileName = GetFileNameForUser(user.UserName);
                fs = File.Open(fileName, FileMode.Open, FileAccess.Read);
                XmlSerializer xs = new XmlSerializer(typeof(PrismUser));
                PrismUser u = (PrismUser)xs.Deserialize(fs);
                user.FromString(u.ToString());
            }
            finally
            {
                if (fs != null)
                    fs.Close();
            }
        }

        //Is the password valid for the user?
        public override bool IsPasswordValid(string userName, string password)
        {
            PrismUser user = new PrismUser();
            user.UserName = userName;
            PopulateUserInfo(user);
            return password.ToUpper() == user.Password.ToUpper();
        }

        //Serialize the user
        public override void StoreUserInfo(PrismUser user)
        {
            FileStream fs = null;
            try
            {
                string fileName = GetFileNameForUser(user.UserName);
                fs = File.Create(fileName);
                XmlSerializer xs = new XmlSerializer(typeof(PrismUser));
                xs.Serialize(fs, user);
            }
            finally
            {
                if (fs != null)
                    fs.Close();
            }
        }

        //Obtain a list of all users
        public override List<PrismUser> GetUserList()
        {
            List<PrismUser> users = new List<PrismUser>();
            string[] files = Directory.GetFiles(_baseDirectory);
            foreach (string fileName in files)
            {
                string userName = Path.GetFileNameWithoutExtension(fileName);
                PrismUser user = new PrismUser();
                user.UserName = userName;
                PopulateUserInfo(user);
                users.Add(user);
            }
            return users;
        }

        //private members
        private string _baseDirectory = "";

        //Get the full file name for a user
        private string GetFileNameForUser(string userName)
        {
            return _baseDirectory + @"\" + userName + ".xml";
        }
    }
}
